package internal

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"gorm.io/gorm"
	"log"
	"net/http"
	"strings"

	"gitee.com/zhuoyue6/wecom_msg/config"
	"gitee.com/zhuoyue6/wecom_msg/pkg/wecom"
	"github.com/gin-gonic/gin"
	"github.com/mozillazg/go-pinyin"
)

// ==================== 用户同步器 ====================

// UserSyncSynchronizer 企业微信用户同步核心结构体
type UserSyncSynchronizer struct {
	ctx         context.Context
	wecomClient *wecom.WecomClient
	userRepo    *WorkWechatUserRepo
}

// SyncResult 同步结果
type SyncResult struct {
	TotalCount   int `json:"total_count"`   // 企业微信总用户数
	SyncedCount  int `json:"synced_count"`  // 新增用户数
	UpdatedCount int `json:"updated_count"` // 更新用户数
	ErrorCount   int `json:"error_count"`   // 错误数量
	SkipCount    int `json:"skip_count"`    // 跳过数量
}

// NewUserSyncSynchronizer 创建用户同步器
func NewUserSyncSynchronizer(ctx context.Context) *UserSyncSynchronizer {
	// 创建企业微信客户端配置
	wecomConfig := &wecom.WecomConfig{
		CorpID:      config.GlobalConfig.Wework.CorpID,
		AgentID:     config.GlobalConfig.Wework.AgentID,
		AppSecret:   config.GlobalConfig.Wework.CorpSecret,
		AgentDomain: config.GlobalConfig.Wework.AgentDomain,
		TokenCache:  nil, // 使用默认内存缓存
		SafeMode:    false,
	}

	// 创建企业微信客户端
	wecomClient := wecom.NewWecomClient(wecomConfig, ctx)

	return &UserSyncSynchronizer{
		ctx:         ctx,
		wecomClient: wecomClient,
		userRepo:    NewWorkWechatUserRepo(ctx),
	}
}

// SyncUsers 同步企业微信用户到数据库（获取全部用户）
func (s *UserSyncSynchronizer) SyncUsers() (*SyncResult, error) {
	log.Printf("开始同步企业微信用户（获取全部用户）")

	// 从企业微信获取全部用户列表（根部门，包含子部门，包含所有状态）
	wecomUsers, err := s.wecomClient.GetUserList(1, true)
	if err != nil {
		return nil, fmt.Errorf("获取企业微信用户列表失败: %v", err)
	}

	log.Printf("从企业微信获取到 %d 个用户", len(wecomUsers))

	result := &SyncResult{
		TotalCount: len(wecomUsers),
	}

	// 遍历用户列表进行同步
	for _, wecomUser := range wecomUsers {
		// 检查用户是否已存在

		var existingUser *WecomUser
		err := s.userRepo.Db.WithContext(s.userRepo.Ctx).Where("userid = ?", wecomUser.UserID).First(&existingUser).Error
		if err != nil {
			if !errors.Is(err, gorm.ErrRecordNotFound) {
				log.Printf("查询用户失败 %s: %v", wecomUser.UserID, err)
				result.ErrorCount++
				continue
			}
		}

		// 构建用户模型
		user := &WecomUser{
			UserID: wecomUser.UserID,
			Name:   wecomUser.Name,
			Alias:  s.generateAlias(wecomUser.Name),
			Status: int8(wecomUser.Status),
		}

		if existingUser == nil {
			// 创建新用户
			if err := s.userRepo.Create(user); err != nil {
				log.Printf("创建用户失败 %s: %v", wecomUser.UserID, err)
				result.ErrorCount++
			} else {
				result.SyncedCount++
				log.Printf("新增用户: %s (%s)", user.Name, user.UserID)
			}
		} else {
			// 检查是否需要更新
			if s.needUpdate(existingUser, user) {
				user.ID = existingUser.ID
				user.CreatedAt = existingUser.CreatedAt
				if err := s.userRepo.Update(user); err != nil {
					log.Printf("更新用户失败 %s: %v", wecomUser.UserID, err)
					result.ErrorCount++
				} else {
					result.UpdatedCount++
					log.Printf("更新用户: %s (%s)", user.Name, user.UserID)
				}
			} else {
				result.SkipCount++
			}
		}
	}

	log.Printf("用户同步完成 - 总数: %d, 新增: %d, 更新: %d, 错误: %d, 跳过: %d",
		result.TotalCount, result.SyncedCount, result.UpdatedCount, result.ErrorCount, result.SkipCount)

	// 清除缓存
	NewWorkWechatUserRepo(s.ctx).ClearAllCache()
	return result, nil
}

// generateAlias 生成用户别名（真实名称转拼音小写）
func (s *UserSyncSynchronizer) generateAlias(name string) string {
	if name == "" {
		return ""
	}

	// 将中文转换为拼音
	pinyinSlice := pinyin.LazyConvert(name, nil)

	// 将拼音数组连接成字符串并转换为小写
	pinyinStr := strings.Join(pinyinSlice, "")

	// 转换为小写
	return strings.ToLower(pinyinStr)
}

// needUpdate 判断是否需要更新用户信息
func (s *UserSyncSynchronizer) needUpdate(existing, new *WecomUser) bool {
	return existing.Name != new.Name ||
		existing.Alias != new.Alias ||
		existing.Status != new.Status
}

// SyncUsersAPI 同步用户数据API处理函数
func (s *UserSyncSynchronizer) SyncUsersAPI(c *gin.Context) {
	// 执行用户同步
	result, err := s.SyncUsers()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code": 500,
			"msg":  "同步用户数据失败",
			"data": gin.H{
				"error": err.Error(),
			},
		})
		return
	}

	// 返回同步结果
	c.JSON(http.StatusOK, gin.H{
		"code": 0,
		"msg":  "同步用户数据成功",
		"data": result,
	})
}

// ==================== 消息发送器 ====================

// MessageSender 消息发送器
type MessageSender struct {
	ctx         context.Context
	wecomClient *wecom.WecomClient
	messageRepo *WecomMessageRecordRepo
	userRepo    *WorkWechatUserRepo // 添加userRepo字段用于缓存共享
}

// NewMessageSender 创建消息发送器
func NewMessageSender(ctx context.Context) *MessageSender {
	// 创建企业微信客户端配置
	wecomConfig := &wecom.WecomConfig{
		CorpID:      config.GlobalConfig.Wework.CorpID,
		AgentID:     config.GlobalConfig.Wework.AgentID,
		AppSecret:   config.GlobalConfig.Wework.CorpSecret,
		AgentDomain: config.GlobalConfig.Wework.AgentDomain,
		TokenCache:  nil, // 使用默认内存缓存
		SafeMode:    false,
	}

	// 创建企业微信客户端
	wecomClient := wecom.NewWecomClient(wecomConfig, ctx)

	return &MessageSender{
		ctx:         ctx,
		wecomClient: wecomClient,
		messageRepo: NewWecomMessageRecordRepo(ctx),
		userRepo:    NewWorkWechatUserRepo(ctx), // 初始化userRepo
	}
}

// 发送消息的通用处理逻辑
func (s *MessageSender) sendMessageCommon(c *gin.Context, messageType string, req *MessageRequest) {
	if req.UserAlias == "admin" {
		req.UserAlias = config.GlobalConfig.Server.AdminAliasMap
	}

	// 通过user_alias查找用户
	user, err := s.userRepo.GetByAlias(req.UserAlias)
	if err != nil || user == nil {
		c.JSON(http.StatusBadRequest, MessageResponse{
			Code:    400,
			Message: "用户不存在",
			Data:    gin.H{"error": fmt.Sprintf("用户别名 %s 不存在", req.UserAlias)},
		})
		return
	}

	if user.Status != 1 {
		c.JSON(http.StatusBadRequest, MessageResponse{
			Code:    400,
			Message: "用户异常或已离职",
			Data:    gin.H{"error": fmt.Sprintf("用户别名 %s 异常或已离职", req.UserAlias)},
		})
		return
	}

	// 创建消息记录
	jsonContent, _ := json.Marshal(req.Content)

	record := &WecomMessageRecord{
		MessageType: messageType,
		ToUser:      user.UserID,
		UserAlias:   req.UserAlias,
		Title:       req.Title,
		Content:     string(jsonContent),
		Status:      string(SendMsgStatusWaiting),
	}

	// 发送消息
	err = s.sendMessage(messageType, req, user.UserID)
	if err != nil {
		// 更新消息记录状态为失败
		record.Status = string(SendMsgStatusFail)
		record.ErrorMsg = err.Error()
		_ = s.messageRepo.Create(record)

		c.JSON(http.StatusInternalServerError, MessageResponse{
			Code:    500,
			Message: "发送消息失败",
			Data:    gin.H{"error": err.Error()},
		})
		return
	}

	// 更新消息记录状态为成功
	record.Status = string(SendMsgStatusSuccess)
	_ = s.messageRepo.Create(record)

	c.JSON(http.StatusOK, MessageResponse{
		Code:    0,
		Message: "发送消息成功",
		Data:    gin.H{"record_id": record.ID},
	})
}

// 根据消息类型发送消息
func (s *MessageSender) sendMessage(messageType string, req *MessageRequest, toUser string) error {
	msgType := MessageType(messageType)

	switch msgType {
	case MessageTypeMarkdown:
		return s.sendMarkdownMessage(req, toUser)
	case MessageTypeText:
		return s.sendTextMessage(req, toUser)
	default:
		return fmt.Errorf("不支持的消息类型: %s", messageType)
	}
}

// 发送Markdown消息
func (s *MessageSender) sendMarkdownMessage(req *MessageRequest, toUser string) error {
	// 调用企业微信API发送Markdown消息

	contentStr := strings.Join(req.Content, "\n>")
	contentStr = "\n>" + contentStr
	contentStr = "### " + req.Title + "\r\n\r\n" + contentStr
	// 构建基础请求体
	body := map[string]interface{}{
		"agentid":  s.wecomClient.GetAgentID(),
		"touser":   toUser,
		"msgtype":  "markdown",
		"markdown": map[string]string{"content": contentStr},
	}
	err := s.sendWecomMessage(body)
	return err
}

// 发送文本消息
func (s *MessageSender) sendTextMessage(req *MessageRequest, toUser string) error {
	// 构建文本消息请求体
	body := map[string]interface{}{
		"agentid": s.wecomClient.GetAgentID(),
		"touser":  toUser,
		"msgtype": "text",
		"text":    map[string]string{"content": req.Title + "\n\n" + strings.Join(req.Content, "\n")},
	}

	return s.sendWecomMessage(body)
}

// sendWecomMessage 发送企业微信消息的通用方法
func (s *MessageSender) sendWecomMessage(body map[string]interface{}) error {
	jsonBody, err := json.Marshal(body)
	if err != nil {
		return fmt.Errorf("序列化消息体失败: %v", err)
	}

	// 调用企业微信API发送消息
	return s.wecomClient.SendMessage(jsonBody)
}
